package springfox.documentation.spring.web;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import springfox.documentation.service.*;

import java.util.*;

import static com.google.common.collect.Maps.newLinkedHashMap;

public class DocumentationCache {
    private Map<String, Documentation> documentationLookup = newLinkedHashMap();

    public void addDocumentation(Documentation documentation) {
        documentationLookup.put(documentation.getGroupName(), documentation);
    }

    public Documentation documentationByGroup(String groupName, String keyword) {
        if (null != keyword && !"".equals(keyword.trim())) {
            Documentation document = documentationLookup.get(groupName);

            try {
                List<ApiDescription> newApis = new ArrayList<>();

                Multimap<String, ApiListing> newApiListings = ArrayListMultimap.create();
                Set<Tag> newTags = new HashSet<>(document.getTags());
                ResourceListing newResourceListing = document.getResourceListing();
                Set<String> newProduces = new HashSet<>(document.getProduces());
                Set<String> newConsumes = new HashSet<>(document.getConsumes());
                Set<String> newSchemes = new HashSet<>(document.getSchemes());

                Multimap<String, ApiListing> apiListings = document.getApiListings();
                Iterator<Map.Entry<String, ApiListing>> iterator = apiListings.entries().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, ApiListing> next = iterator.next();
                    String key = next.getKey();
                    ApiListing apiList = next.getValue();
                    List<ApiDescription> apis = apiList.getApis();
                    for (int i = 0; i < apis.size(); i++) {
                        ApiDescription api = apis.get(i);
                        String path = api.getPath();
                        List<Operation> operations = api.getOperations();
                        if (
                                (operations.size() > 0 && null != operations.get(0) &&
                                        ((null != operations.get(0).getNotes() && operations.get(0).getNotes().contains(keyword))
                                                ||(null != operations.get(0).getSummary() && operations.get(0).getSummary().contains(keyword))))
                                        || path.contains(keyword)) {
                            newApis.add(api);
                        }
                    }
                    ApiListing newApiListing = new ApiListing(apiList.getApiVersion(), apiList.getBasePath(),
                            apiList.getResourcePath(), apiList.getProduces(), apiList.getConsumes(), apiList.getHost(),
                            apiList.getProtocols(), apiList.getSecurityReferences(), newApis, apiList.getModels(),
                            apiList.getDescription(), apiList.getPosition(), apiList.getTags());
                    newApiListings.put(key, newApiListing);
                }
                Documentation newDocument = new Documentation(document.getGroupName(), document.getBasePath(), newTags,
                        newApiListings, newResourceListing, newProduces, newConsumes, document.getHost(), newSchemes, document.getVendorExtensions());
                return newDocument;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return document;
        } else {
            return documentationLookup.get(groupName);
        }
//    return documentationLookup.get(groupName);
    }

    public Map<String, Documentation> all() {
        return Collections.unmodifiableMap(documentationLookup);
    }

    public void clear() {
        documentationLookup.clear();
    }
}